//域名与IP地址对应的map的相关操作
#include <stdio.h>
#include <fstream>
#include <string.h>

#include"hashmap.h"
#include"list.h"

#define MAX_CACHE_SIZE 10          // cache中最多可以存储的记录量
#define URL_LEN 64                 // url长度
#define IP_LEN 15                  // IP长度
#define MAX_ID_TRANS_TABLE_SIZE 128 // ID转换表的最大尺寸

typedef struct
{
    unsigned short old_ID; //客户端报文ID
    SOCKADDR_IN client;    //客户端地址
    int expire_time;       //判断超时
} ID_Trans_Table;          //记录向DNS服务器查询的数据

typedef Hash_Map* Local_Table; //存储本地的记录,cache容量超限也会放入一部分记录
typedef Hash_Map* Cache;       //存储最近查询记录
typedef List* Cache_LRU_List;     //由于map会自动排序,所以通过一个list来保存查询次序

void printf_IPmap(Hash_Map *hashmap)
{
    printf("\n\n----------------------------\n");
    print_map(hashmap);
    printf("\n----------------------------\n");
    return;
}

int read_from_txt(Local_Table local_table, int debug_level,char *file_path)
{
    //从文件中读取IP地址与域名,成功则返回读取的个数,若读取错误则返回-1
    //由于c没有string,所以直接用scanf会报错
    if (file_path == NULL)
        file_path = (char *)"dnsrelay.txt";
    FILE *file;
    int mapnum = 0;
    char url[65], ip[16];
    if ((file = fopen(file_path, "r")) == NULL)
        return -1;
    while (fscanf(file, "%s %s", ip, url) > 0)
    {
        mapnum++;
        if (debug_level >= 1)
            printf("read from txt:[Url:%s ,IP:%s]\n",  url, ip);
        hash_map_insert(local_table,url,ip);
    }
    fclose(file);
    return mapnum;
}

int add_to_cache(Cache cache, Local_Table local_table, Cache_LRU_List cache_lru_list, char* url, char* ip, int debug_level)
{
    //添加记录到IPmap,如果是覆盖掉原来记录返回1,如果是新添加记录返回0
    //如果cache中的数据量已达上限,则会将最早的一条记录转移到存储本地记录的local_table中,返回2
    int func_type = 0; //执行操作的种类
    //cache_lru_list中成功删除url，则代表cache中包含这对url与ip
    if (list_remove(cache_lru_list,url) == 1)
        func_type = 1;
    if (map_size(cache) >= MAX_CACHE_SIZE)
    {
        char* old_url = list_front(cache_lru_list);
        list_pop_front(cache_lru_list);
        hash_map_remove(cache,old_url);
        func_type = 2;
    }
    hash_map_insert(cache, url, ip);
    list_pushback(cache_lru_list,url);
    if (debug_level >= 1)
        printf_IPmap(cache);
    return func_type;
}

void Set_ID_Expire(ID_Trans_Table *record, int ttl)
{
    //设置向服务器请求的ttl
    record->expire_time = time(NULL) + ttl;
}

int Check_ID_Expired(ID_Trans_Table *record)
{
    //判断向服务器的请求是否超时,是为真
    return record->expire_time > 0 && time(NULL) > record->expire_time;
}